package com.billdowney.aop;

import java.lang.reflect.Method;
import java.util.regex.Pattern;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.billdowney.annotation.SystemLogInfo;

import cn.hutool.json.JSONObject;

/**
 * 用户操作记录AOP类
 * 
 * @author 超级小富翁 - BillDowney
 * @data 2017年7月21日 上午10:26:33
 */
//@Component
//@Aspect
public class UserOperationLogAop {

	private Logger log = LoggerFactory.getLogger(UserOperationLogAop.class);

	/**
	 * 切入点配置
	 * 
	 * @anthor billdonwey
	 */
	@Pointcut("execution(public * com.billdowney.controller..*(..))")
	public void pointcut() {
	}

	/**
	 * 环绕通知AOP
	 * 
	 * @params pjp 必传参数，包含了目标类的所有信息
	 * @return 返回的是目标方法的返回值，固定格式
	 * @throws Throwable, Exception
	 * @anthor billdonwey
	 */
	@Around("pointcut()")
	public Object around(ProceedingJoinPoint pjp) throws Throwable, Exception {
		// 新建输出到日志的字符串
		JSONObject info = new JSONObject();
		// 设置访问用户
		info.put("user", "系统日志");
		// 设置提示信息，可以为空
		info.put("msg", assembleLogInfo(pjp));
		// 设置访问的包名和类名
		info.put("class", pjp.getTarget().getClass().getName());
		// 设置访问的方法
		info.put("method", pjp.getSignature().getName());
		// 设置传入的参数
		StringBuffer args = new StringBuffer();
		for (Object o : pjp.getArgs()) {
			args.append(o + ",");
		}
		if (args.length() > 0) {
			args.replace(args.length() - 1, args.length(), "");
		}
		info.put("args", args.toString());
		// 定义调用函数返回的对象
		Object obj = null;
		obj = pjp.proceed();
		// 设置返回的参数
		// info.put("return", obj);
		// 记录日志信息
		log.info(info.toString());
		return obj;
	}

	/**
	 * 拼装日志信息
	 * 
	 * @params pjp 传入的ProceedingJoinPoint类
	 * @return 返回拼装好的日志信息
	 * @anthor billdonwey
	 */
	public String assembleLogInfo(ProceedingJoinPoint pjp) {
		StringBuffer str = new StringBuffer();
		try {
			str.append("msg:");
			// 获取目标类
			Class<?> c = Class.forName(pjp.getTarget().getClass().getName());
			// 获取目标方法
			Method m = null;
			for (Method method : c.getDeclaredMethods()) {
				if (method.getName().equals(pjp.getSignature().getName())) {
					m = method;
					break;
				}
			}
			// 得到注解信息
			SystemLogInfo logInfo = m.getAnnotation(SystemLogInfo.class);
			// 得到注解日志信息
			str.append(logInfo.value());
			// 获取方法中传入的参数
			Object[] args = pjp.getArgs();
			// 替换参数值
			while (Pattern.matches(".*\\{\\d+\\}.*", str)) {
				String s = str.substring(str.indexOf("{") + 1, str.indexOf("}"));
				str.replace(str.indexOf("{"), str.indexOf("}") + 1, args[Integer.parseInt(s)].toString());
			}
			str.append(";");
		} catch (ClassNotFoundException e) {
			// e.printStackTrace();
			return "";
		} catch (SecurityException e) {
			// e.printStackTrace();
			return "";
		} catch (Exception e) {
			// e.printStackTrace();
			return "";
		}
		return str.toString();
	}

}
